D:\git\skunkworks\herald-for-cpp\herald-tests\analysissensor-tests.cpp
Line | Count | Source |
1 | | // Copyright 2021 Herald project contributors |
2 | | // SPDX-License-Identifier: Apache-2.0 |
3 | | // |
4 | | |
5 | | #include "test-templates.h" |
6 | | |
7 | | #include "catch.hpp" |
8 | | |
9 | | #include "herald/herald.h" |
10 | | |
11 | | #include <utility> |
12 | | #include <iostream> |
13 | | |
14 | | using namespace herald; |
15 | | using namespace herald::analysis::sampling; |
16 | | using namespace herald::datatype; |
17 | | |
18 | | struct DummyDistanceDelegate { |
19 | | using value_type = Distance; |
20 | | |
21 | | DummyDistanceDelegate() : lastSampledID(0), distances() {}; |
22 | | DummyDistanceDelegate(const DummyDistanceDelegate&) = delete; // copy ctor deleted |
23 | | DummyDistanceDelegate(DummyDistanceDelegate&& other) noexcept : lastSampledID(other.lastSampledID), distances(std::move(other.distances)) {} // move ctor |
24 | | ~DummyDistanceDelegate() {}; |
25 | | |
26 | | DummyDistanceDelegate& operator=(DummyDistanceDelegate&& other) noexcept { |
27 | | lastSampledID = other.lastSampledID; |
28 | | std::swap(distances,other.distances); |
29 | | return *this; |
30 | | } |
31 | | |
32 | | // specific override of template |
33 | | void newSample(SampledID sampled, Sample<Distance> sample) { |
34 | | lastSampledID = sampled; |
35 | | distances.push(sample); |
36 | | } |
37 | | |
38 | | void reset() { |
39 | | distances.clear(); |
40 | | lastSampledID = 0; |
41 | | } |
42 | | |
43 | | // Test only methods |
44 | | SampledID lastSampled() { |
45 | | return lastSampledID; |
46 | | } |
47 | | |
48 | | const SampleList<Sample<Distance>,25>& samples() { |
49 | | return distances; |
50 | | } |
51 | | |
52 | | private: |
53 | | SampledID lastSampledID; |
54 | | SampleList<Sample<Distance>,25> distances; |
55 | | }; |
56 | | |
57 | | /// [Who] As a DCT app developer |
58 | | /// [What] I want to link my live application data to an analysis runner easily |
59 | | /// [Value] So I don't have to write plumbing code for Herald itself |
60 | | /// |
61 | | /// [Who] As a DCT app developer |
62 | | /// [What] I want to periodically run analysis aggregates automatically |
63 | | /// [Value] So I don't miss any information, and have accurate, regular, samples |
64 | 1 | TEST_CASE("analysissensor-rssi-basic", "[analysissensor][rssi][basic]") { |
65 | 1 | SECTION("analysissensor-rssi-basic") { |
66 | 1 | Proximity p1{.unit = ProximityMeasurementUnit::RSSI, .value = -55}; |
67 | 1 | Proximity p2{.unit = ProximityMeasurementUnit::RSSI, .value = -56}; |
68 | 1 | Proximity p3{.unit = ProximityMeasurementUnit::RSSI, .value = -57}; |
69 | 1 | Proximity p4{.unit = ProximityMeasurementUnit::RSSI, .value = -58}; |
70 | 1 | |
71 | 1 | herald::analysis::algorithms::distance::FowlerBasicAnalyser distanceAnalyser(0, -50, -24); // 0 = run every time run() is called |
72 | 1 | |
73 | 1 | DummyDistanceDelegate myDelegate; |
74 | 1 | herald::analysis::AnalysisDelegateManager adm(std::move(myDelegate)); // NOTE: myDelegate MOVED FROM and no longer accessible |
75 | 1 | herald::analysis::AnalysisProviderManager apm(std::move(distanceAnalyser)); // NOTE: distanceAnalyser MOVED FROM and no longer accessible |
76 | 1 | |
77 | 1 | herald::analysis::AnalysisRunner< |
78 | 1 | herald::analysis::AnalysisDelegateManager<DummyDistanceDelegate>, |
79 | 1 | herald::analysis::AnalysisProviderManager<herald::analysis::algorithms::distance::FowlerBasicAnalyser>, |
80 | 1 | RSSI,Distance |
81 | 1 | > runner(adm, apm); // just for Sample<RSSI> types, and their produced output (Sample<Distance>) |
82 | 1 | |
83 | 1 | herald::analysis::SensorDelegateRSSISource<decltype(runner)> src(runner); |
84 | 1 | PayloadData payload(std::byte(5),4); |
85 | 1 | TargetIdentifier id(Data(std::byte(3),16)); |
86 | 1 | src.sensor(SensorType::BLE, p1, id, payload); |
87 | 1 | src.sensor(SensorType::BLE, p2, id, payload); |
88 | 1 | runner.run(Date()); // In an app, use a Coordinator task |
89 | 1 | src.sensor(SensorType::BLE, p3, id, payload); |
90 | 1 | src.sensor(SensorType::BLE, p4, id, payload); |
91 | 1 | runner.run(Date()); // In an app, use a Coordinator task |
92 | 1 | |
93 | 1 | auto& delegateRef = adm.get<DummyDistanceDelegate>(); |
94 | 1 | REQUIRE(delegateRef.lastSampled() != 0); |
95 | 1 | |
96 | 1 | auto& samples = delegateRef.samples(); |
97 | 1 | REQUIRE(samples.size() == 1); // Only 1 because time will run in 'real time' as its a sensor source (dynamic date) |
98 | 1 | REQUIRE(samples[0].taken.secondsSinceUnixEpoch() != 0); |
99 | 1 | REQUIRE(samples[0].value != 0.0); |
100 | 1 | |
101 | 1 | // Let's see the total memory in use... |
102 | 1 | std::cout << "AnalysisRunner::RAM = " << sizeof(runner) << std::endl; |
103 | 1 | std::cout << "SensorDelegateRSSISource::RAM = " << sizeof(src) << std::endl; |
104 | 1 | } |
105 | 1 | } |
106 | | |
107 | | |
108 | | |
109 | 1 | TEST_CASE("analysissensor-output", "[sensorlogger][analysissensor][output]") { |
110 | 1 | SECTION("analysissensor-output") { |
111 | 1 | DummyLoggingSink dls; |
112 | 1 | DummyBluetoothStateManager dbsm; |
113 | 1 | herald::DefaultPlatformType dpt; |
114 | 1 | herald::Context ctx(dpt,dls,dbsm); // default context include |
115 | 1 | using CT = typename herald::Context<herald::DefaultPlatformType,DummyLoggingSink,DummyBluetoothStateManager>; |
116 | 1 | //herald::data::SensorLogger logger(ctx,"testout","analysissensor"); |
117 | 1 | herald::analysis::LoggingAnalysisDelegate<CT,Distance> lad(ctx); // The subject of this test |
118 | 1 | std::cout << "LoggingAnalysisDelegate::RAM = " << sizeof(lad) << std::endl; |
119 | 1 | |
120 | 1 | |
121 | 1 | Proximity p1{.unit = ProximityMeasurementUnit::RSSI, .value = -55}; |
122 | 1 | Proximity p2{.unit = ProximityMeasurementUnit::RSSI, .value = -56}; |
123 | 1 | Proximity p3{.unit = ProximityMeasurementUnit::RSSI, .value = -57}; |
124 | 1 | Proximity p4{.unit = ProximityMeasurementUnit::RSSI, .value = -58}; |
125 | 1 | |
126 | 1 | herald::analysis::algorithms::distance::FowlerBasicAnalyser distanceAnalyser(0, -50, -24); // 0 = run every time run() is called |
127 | 1 | |
128 | 1 | DummyDistanceDelegate myDelegate; |
129 | 1 | herald::analysis::AnalysisDelegateManager adm(std::move(myDelegate), std::move(lad)); // NOTE: myDelegate MOVED FROM and no longer accessible |
130 | 1 | herald::analysis::AnalysisProviderManager apm(std::move(distanceAnalyser)); // NOTE: distanceAnalyser MOVED FROM and no longer accessible |
131 | 1 | |
132 | 1 | herald::analysis::AnalysisRunner< |
133 | 1 | herald::analysis::AnalysisDelegateManager<DummyDistanceDelegate,herald::analysis::LoggingAnalysisDelegate<CT,Distance>>, |
134 | 1 | herald::analysis::AnalysisProviderManager<herald::analysis::algorithms::distance::FowlerBasicAnalyser>, |
135 | 1 | RSSI,Distance |
136 | 1 | > runner(adm, apm); // just for Sample<RSSI> types, and their produced output (Sample<Distance>) |
137 | 1 | |
138 | 1 | herald::analysis::SensorDelegateRSSISource<decltype(runner)> src(runner); |
139 | 1 | PayloadData payload(std::byte(5),4); |
140 | 1 | TargetIdentifier id(Data(std::byte(3),16)); |
141 | 1 | src.sensor(SensorType::BLE, p1, id, payload); |
142 | 1 | src.sensor(SensorType::BLE, p2, id, payload); |
143 | 1 | runner.run(Date()); // In an app, use a Coordinator task |
144 | 1 | src.sensor(SensorType::BLE, p3, id, payload); |
145 | 1 | src.sensor(SensorType::BLE, p4, id, payload); |
146 | 1 | runner.run(Date()); // In an app, use a Coordinator task |
147 | 1 | |
148 | 1 | auto& delegateRef = adm.get<DummyDistanceDelegate>(); |
149 | 1 | REQUIRE(delegateRef.lastSampled() != 0); |
150 | 1 | |
151 | 1 | auto& samples = delegateRef.samples(); |
152 | 1 | REQUIRE(samples.size() == 1); // Only 1 because time will run in 'real time' as its a sensor source (dynamic date) |
153 | 1 | REQUIRE(samples[0].taken.secondsSinceUnixEpoch() != 0); |
154 | 1 | REQUIRE(samples[0].value != 0.0); |
155 | 1 | |
156 | 1 | auto lastMsg = dls.value; |
157 | 1 | REQUIRE(lastMsg != ""); // must have logged something... |
158 | 1 | std::cout << "Last log message: " << lastMsg << std::endl; |
159 | 1 | |
160 | 1 | // Let's see the total memory in use... |
161 | 1 | std::cout << "AnalysisRunner::RAM = " << sizeof(runner) << std::endl; |
162 | 1 | std::cout << "SensorDelegateRSSISource::RAM = " << sizeof(src) << std::endl; |
163 | 1 | |
164 | 1 | |
165 | 1 | } |
166 | 1 | } |